home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / UTIL / FILEUTIL / SUPPORT100 / Source / Splitf_c < prev    next >
Text File  |  1995-02-04  |  19KB  |  391 lines

  1. /********************************************************************************/
  2. /*                                                                              */
  3. /* Splitf.c                                                                     */
  4. /* Part of Splitf and Joinf distribution                                        */
  5. /* version 1.13, © 1993-1995 Adam Hamilton                                      */
  6. /* See the README file for copyright information                                */
  7. /*                                                                              */
  8. /********************************************************************************/
  9.  
  10.  
  11. /*********************************/
  12. /* Include required header files */
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include "config.h"
  18.  
  19.  
  20. /**********************************/
  21. /* Program macros and definitions */
  22.  
  23. #ifndef Bool
  24. #  define Bool char
  25. #endif
  26.  
  27. #define False   0
  28. #define True    !False
  29. #define MIN(a, b) (a < b ? a : b)
  30. #define MAX(a, b) (a > b ? a : b)
  31.  
  32. #ifndef LEAFNAME_MAX
  33. #  define LEAFNAME_MAX  FILENAME_MAX
  34. #endif
  35.  
  36.  
  37.  
  38. /********************************************************************************/
  39. /*                                                                              */
  40. /* Function    : usage                                                          */
  41. /* Description : Displays program usage to standard error, and exits.           */
  42. /* Arguments   : progname - pointer to character string containing the program  */
  43. /*                          name.                                               */
  44. /* Returns     : None.                                                          */
  45. /*                                                                              */
  46. /********************************************************************************/
  47.  
  48.  
  49. void usage (char *progname)
  50. {
  51.   fprintf (stderr, "File splitter. Version 1.13 - 4th Feburary 1995 by A.Hamilton\n\n");
  52.   fprintf (stderr, "Usage : %s [options] <filename>\n\n", progname);
  53.   fprintf (stderr, "Options (can be abbreviated) :\n");
  54.   fprintf (stderr, "    -filesize     [filesize in K]          default = 1423\n");
  55. #ifndef PC
  56.   fprintf (stderr, "    -buffersize   [buffersize in K]        default = 32\n");
  57. #endif
  58.   fprintf (stderr, "    -path         [new path]\n");
  59.   fprintf (stderr, "    -interactive\n");
  60.  
  61.   exit (EXIT_FAILURE);
  62. }
  63.  
  64.  
  65.  
  66. /********************************************************************************/
  67. /*                                                                              */
  68. /* Function    : examine_filename                                               */
  69. /* Description : Splits filename into component parts.                           */
  70. /* Arguments   : original_name - character array, filename to be examined.      */
  71. /*               name          - pointer to a character array in which to store */
  72. /*                               file leafname (excluding extention).           */
  73. /*               ext           - pointer to a character array in which to store */
  74. /*                               the source files extention (if any).           */
  75. /* Returns     : If the source file has an extention, then return ".spt",       */
  76. /*               otherwise return "".                                           */
  77. /*                                                                              */
  78. /********************************************************************************/
  79.  
  80.  
  81. char *examine_filename (char original_name[], char *name, char *ext)
  82. {
  83.   char main_name[256];                  /* Temporary store for leafname.        */
  84.   char *original;                       /* Pointer to start of leafname.        */
  85.   char *pointer;                        /* Pointer to any ':' characters found. */
  86.   register int i = -1, n;               /* Pointer & counter.                   */
  87.  
  88.  
  89.   if (COLON)                                                    /* If our system uses ':' in    */
  90.     pointer = strrchr (original_name, ':');                     /* the file path, then remember */
  91.   else                                                          /* where it is.                 */
  92.     pointer = NULL;
  93.  
  94.   original = strrchr (original_name, SEPARATOR_SEARCH);         /* Find the address where the   */
  95.   if ((original = MAX (original, pointer)) == NULL)             /* leafname starts.             */
  96.     original = original_name;
  97.   else {
  98.     original++;
  99.   }
  100.  
  101.   do {
  102.     i++;
  103.     main_name[i] = original[i];                                 /* Get files leafname           */
  104.   } while (main_name[i] != '.' && main_name[i] != '\0');        /* (excluding any extention).   */
  105.  
  106.   for (n = 0; (ext[n] = original[i]) != '\0'; n++, i++) ;       /* Now copy any extention.      */
  107.  
  108.   if (main_name[i - n] == '\0') {                               /* If the file doesn't have an  */
  109.     strcpy (name, main_name);                                   /* extention, copy the leafname */
  110.     return ("");                                                /* and return an empty string.  */
  111.   }
  112.   main_name[i - n] = '\0';                                      /* Otherwise, terminate the     */
  113.   strcpy (name, main_name);                                     /* leafname, copy it, and       */
  114.   return (".spt");                                              /* the output extention to use. */
  115. }
  116.  
  117.  
  118.  
  119. /********************************************************************************/
  120. /*                                                                              */
  121. /* Function    : numtostr                                                       */
  122. /* Description : Converts a number into a 2 didget character string.            */
  123. /* Arguments   : number - number to be converted.                               */
  124. /*               name   - pointer to a character array to store the number.     */
  125. /* Returns     : None.                                                          */
  126. /*                                                                              */
  127. /********************************************************************************/
  128.  
  129.  
  130. void numtostr (short number, char *name)
  131. {
  132.   name[0] = (short) (number / 10) + '0';
  133.   name[1] = (number % 10) + '0';
  134.   name[2] = '\0';
  135. }
  136.  
  137.  
  138.  
  139. /********************************************************************************/
  140. /*                                                                              */
  141. /* Function    : main                                                           */
  142. /* Description : Main control function.                                         */
  143. /* Arguments   : Command line parameters.                                       */
  144. /* Returns     : Exit status.                                                   */
  145. /*                                                                              */
  146. /********************************************************************************/
  147.  
  148.  
  149. int main (int argc, char **argv)
  150. {
  151.   char  source_filename[256];           /* Source filename.                     */
  152.   char  out_filename[256];              /* Output leafname.                     */
  153.   char  out_path[256];                  /* Output path.                         */
  154.   char  file_ext[32];                   /* Output extention.                    */
  155.   char  out_name[256];                  /* Full output filename.                */
  156.   char  header[50];                     /* Output file header.                  */
  157.   char  fnum[3];                        /* Output part number.                  */
  158.   char  *progname;                      /* Program name.                        */
  159.   char  string[256];                    /* Input string.                        */
  160.   char  type[5];                        /* Filetype (Acorn systems only).       */
  161.   char  interactive = 0;                /* Interactive status flag.             */
  162.   char  orig_ext[20];                   /* Original filename extention.         */
  163.  
  164.   short file_number = 0;                /* Current part number.                 */
  165.   long  disk_size = 1423 * 1024;        /* Output part size (default 1423K).    */
  166.   long  read_size = 32 * 1024;          /* Buffer size (default 32K).           */
  167.   long  data_size;
  168.   long  out_position;                   /* Position within output file.         */
  169.   long  in_position;                    /* Position within input file.          */
  170.   long  bytes_read;                     /* Number of bytes read.                */
  171.   long  bytes_written;                  /* Number of bytes written.             */
  172.   long  file_length;                    /* Length of source file.               */
  173.   long  *buffer;                        /* Pointer to buffer.                   */
  174.   int   args;                           /* Number of command line arguments.    */
  175.   int   i;                              /* Counter.                             */
  176.   FILE  *source_file;                   /* Source file ID.                      */
  177.   FILE  *out_file;                      /* Output file ID.                      */
  178.  
  179.  
  180. #ifdef ACORN
  181.   _kernel_swi_regs regs;
  182.   _kernel_oserror *err;
  183. #endif
  184.  
  185.   progname = *argv;                                     /* Get the program name.                */
  186.  
  187.   out_path[0] = '\0';                                   /* Set path to CWD.                     */
  188.   source_filename[0] = '\0';                            /* Clear source filename.               */
  189.   strcpy (type, "0");                                   /* No filetype set.                     */
  190.  
  191.   args = argc - 1;                                      /* Initialise count of arguments.       */
  192.   if (!args) usage (progname);                          /* If no arguments supplied, show usage.*/
  193.  
  194.   while (args--) {
  195.     argv++;                                             /* Look at next argument.               */
  196.  
  197.     if (!strncmp ("-filesize", *argv, MAX (2, strlen (*argv)))) {       /* -filesize            */
  198.       if (!args) {
  199.         fprintf (stderr, "File size required.\n\n");
  200.         usage (progname);
  201.       }
  202.       disk_size = (long) atoi (*++argv) * 1024;                         /* Read file size.      */
  203.       args--;
  204.     }
  205.  
  206. #ifndef PC
  207.     else if (!strncmp ("-buffersize", *argv, MAX (2, strlen (*argv)))) {        /* -buffersize  */
  208.       if (!args) {
  209.         fprintf (stderr, "Buffer size required\n\n");
  210.         usage (progname);
  211.       }
  212.       read_size = (long) atoi (*++argv) * 1024;                         /* Read buffer size.    */
  213.       args--;
  214.     }
  215. #endif
  216.  
  217.     else if (!strncmp ("-path", *argv, MAX (2, strlen (*argv)))) {      /* -path                */
  218.       if (!args) {
  219.         fprintf (stderr, "Path required\n\n");
  220.         usage (progname);
  221.       }
  222.       sprintf (out_path, "%s%c", *++argv, FILE_SEPARATOR);              /* Read new output path.*/
  223.       args--;
  224.     }
  225.  
  226.     else if (!strncmp ("-interactive", *argv, MAX (2, strlen (*argv)))) /* -interactive         */
  227.       interactive = 1;
  228.  
  229.     else {
  230.       strcpy (source_filename, *argv);                                  /* Read source filename.*/
  231.       if (args) usage (progname);
  232.     }
  233.   }
  234.  
  235.   if (source_filename[0] == NULL) {
  236.     fprintf (stderr, "Source filename required\n\n");
  237.     usage (progname);
  238.   }
  239.  
  240.                                                         /* Get file detail from source filename.*/
  241.   strcpy (file_ext, examine_filename (source_filename, out_filename, orig_ext));
  242.   out_filename[MIN (LEAFNAME_MAX, 256) - 2] = '\0';     /* and reduce if necessary.             */
  243.  
  244.   source_file = fopen (source_filename, "rb");          /* Open read binary source file.        */
  245.   if (source_file == NULL) {                            /* Report if error, and stop.           */
  246.     fprintf (stderr, "Fatal error opening %s for input.\n", source_filename);
  247.     exit (EXIT_FAILURE);
  248.   }
  249.  
  250.   printf ("Using file size of %ld bytes.\n", disk_size);
  251.   fseek (source_file, 0L, SEEK_END);                    /* Set file pointer to end of file,     */
  252.   file_length = ftell (source_file);                    /* get file length                      */
  253.   fseek (source_file, 0L, SEEK_SET);                    /* and reset pointer to the start.      */
  254.   if (file_length <= disk_size) {
  255.     fprintf (stderr, "No need to split file.\n");
  256.     fclose (source_file);
  257.     exit (EXIT_SUCCESS);
  258.   }
  259.  
  260.   buffer = (long *) malloc ((size_t) read_size);        /* Allocate memory for a buffer.        */
  261.   if (buffer == NULL) {
  262.     fprintf (stderr, "Fatal error, unable to allocate memory block of %ld bytes\n", read_size);
  263.     exit (EXIT_FAILURE);
  264.   }
  265.  
  266.   printf ("Using buffer size of %ld bytes.\n", read_size);
  267.  
  268. #ifdef ACORN
  269.   regs.r[0] = 5;                                /* Perform an OS_File to read file data.        */
  270.   regs.r[1] = (int) source_filename;
  271.   err = _kernel_swi (SWI_OS_File, ®s, ®s);
  272.   if (err != NULL || (regs.r[0] != 1 && regs.r[0] != 3)) {
  273.     fprintf (stderr, "Fatal error, %s is not a file\n", source_filename);
  274.     exit (EXIT_FAILURE);
  275.   }
  276.   sprintf (type, "t%x", (0xFFF & regs.r[2] >> 8));
  277. #endif
  278.  
  279.   sprintf (header, "Split:%s%s=%d=%s|", out_filename, orig_ext,         /* Create the output    */
  280.       (int) (file_length / (disk_size - 7 - strlen (out_filename) -     /* file header.         */
  281.       strlen (orig_ext)) + 1), type);
  282.  
  283.   file_number = 0;                              /* Initialise file number counter.              */
  284.   in_position = 0;                              /* Initialise source file position pointer.     */
  285.  
  286.   while (file_length - in_position > 0) {       /* If any data left to transfer                 */
  287.     file_number++;                              /* increment file number counter.               */
  288.     numtostr (file_number, fnum);               /* Convert to a number.                         */
  289.  
  290.     while (interactive == 1) {                  /* If interactive option selected, ask for      */
  291.       printf ("Enter path for %s%s%s (Return for %s) :\n",      /* destination of output file.  */
  292.           out_filename, fnum, file_ext,
  293.           out_path[0] == '\0' ? "current directory" : out_path);
  294.  
  295.       gets (string);                            /* Get output destination.                      */
  296.       if (strchr (string, ' ') != NULL) {
  297.         printf ("Invalid path name.\n");
  298.         continue;
  299.       }
  300.       if (string[0] != '\0') {                  /* If nothing entered, then use the default.    */
  301.         strcpy (out_path, string);
  302.         i = strlen (out_path);
  303.         if (out_path[i - 1] != FILE_SEPARATOR)
  304.           if (!COLON || (COLON && out_path[i - 1] != ':')) {
  305.             out_path[i] = FILE_SEPARATOR;
  306.             out_path[i + 1] = '\0';
  307.           }
  308.  
  309.       }
  310.       interactive = interactive | 2;            /* Set flag to say data has been accepted.      */
  311.     }
  312.  
  313.     interactive = interactive & 1;                      /* Mask off unrequired data.            */
  314.  
  315.                                                         /* Create the full output filename.     */
  316.     sprintf (out_name, "%s%s%s%s", out_path, out_filename, fnum, file_ext);
  317.  
  318.     if (file_number > 1) {                                      /* If it's not the first part,  */
  319.       numtostr (file_number, fnum);                             /* create a smaller header.     */
  320.       sprintf (header, "Sp:%s%s=%s|", out_filename, orig_ext, fnum);
  321.     }
  322.  
  323. #ifdef ACORN
  324.     regs.r[0] = 7;                                              /* Create the file with SWI     */
  325.     regs.r[1] = (int) out_name;                                 /* OS_File 7                    */
  326.     regs.r[2] = 0xdeaddead;
  327.     regs.r[3] = 0xdeaddead;
  328.     regs.r[4] = 0;
  329.     regs.r[5] = (int) MIN (file_length - in_position + strlen (header), disk_size);
  330.     if ((err = _kernel_swi (SWI_OS_File, ®s, ®s)) != NULL) {
  331.       fprintf (stderr, "Fatal error opening %s for output:\n-- %s\n", out_name, err->errmess);
  332.       exit (EXIT_FAILURE);
  333.     }
  334. #endif
  335.  
  336.     out_file = fopen (out_name, "wb");                          /* Open output file.            */
  337.     if (out_file == NULL) {                                     /* Report if error, and stop.   */
  338.       fprintf (stderr, "Fatal error opening %s for output.\n", out_name);
  339.       exit (1);
  340.     }
  341.  
  342.     out_position = 0;                           /* Initialise output file position pointer.     */
  343.     printf ("Writing data to %s\n", out_name);
  344.  
  345.     fprintf (out_file, header);                 /* Write the header information,                */
  346.     out_position = (long) strlen (header);      /* and update the output file pointer.          */
  347.  
  348.     if (disk_size > file_length - in_position + out_position)   /* Set the size of the file we  */
  349.       disk_size = file_length - in_position + out_position;     /* want to write.               */
  350.  
  351.     while (disk_size - out_position > 0) {                      /* While there's any data left  */
  352.       if (disk_size - out_position < read_size)                 /* to transfer                  */
  353.         data_size = disk_size - out_position;
  354.       else
  355.         data_size = read_size;
  356.  
  357.       bytes_read = fread (buffer, 1, (size_t) data_size, source_file);          /* read         */
  358.       bytes_written = fwrite (buffer, 1, (size_t) bytes_read, out_file);        /* and write.   */
  359.  
  360.                                 /* Check to see that all the data has been transfered ok.       */
  361.       if (bytes_written < data_size && bytes_written < file_length - out_position) {
  362.         fprintf (stderr, "Fatal error while writing %s\n", out_name);
  363.         exit (EXIT_FAILURE);                                    /* If unsucessfull, stop.       */
  364.       }
  365.       in_position += bytes_read;                                /* Update the file position     */
  366.       out_position += bytes_written;                            /* pointers.                    */
  367.     }
  368.  
  369.     fclose (out_file);                                          /* Close output file.           */
  370.  
  371. #ifdef ACORN
  372.     regs.r[0] = 18;                                             /* Set the filetype with SWI    */
  373.     regs.r[1] = (int) out_name;                                 /* OS_File 18                   */
  374.     regs.r[2] = SPLIT_FILETYPE;
  375.     err = _kernel_swi (SWI_OS_File, ®s, ®s);
  376. #endif
  377.  
  378.   }
  379.  
  380.   fclose (source_file);                                                 /* Close source file    */
  381.   free (buffer);                                                        /* and free buffer.     */
  382.  
  383.   fprintf (stderr, "%ld bytes written to %d %s.\n", in_position +
  384.       (int) (file_number * (7 + strlen (source_filename))) + 4 + strlen (type),
  385.       file_number, (file_number == 1) ? "file" : "files");              /* Report status.       */
  386.   fprintf (stderr, "Use : joinf %s01%s \nto restore file.\n",
  387.       out_filename, (file_ext[0] == '\0') ? "" : ".spt");
  388.  
  389.   exit (EXIT_SUCCESS);                                                  /* and finish.          */
  390. }
  391.